﻿namespace TestTool.Tests.Common.Media
{
    using System;
    using System.Collections.Generic;
    using System.Threading;
    using TestTool.Proxies.Onvif;
    using TestTool.Tests.Common.TestEngine;
    using TestTool.Tests.Definitions.Exceptions;
    using TestTool.Tests.Definitions.Interfaces;

    public class VideoUtils
    {
        public static void AdjustVideo(IVideoForm form, string username, string password, int messageTimeout, TransportProtocol protocol, StreamType streamType, MediaUri streamUri, VideoEncoderConfiguration conf)
        {
            if (!string.IsNullOrEmpty(username))
            {
                form.User = username;
            }
            else
            {
                form.User = null;
            }
            if (!string.IsNullOrEmpty(password))
            {
                form.Password = password;
            }
            else
            {
                form.Password = null;
            }
            string str = (streamUri != null) ? streamUri.Uri : null;
            switch (protocol)
            {
                case TransportProtocol.UDP:
                    form.HTTPPort = 0;
                    form.TCP = false;
                    break;

                case TransportProtocol.TCP:
                    form.HTTPPort = 0;
                    form.TCP = true;
                    break;

                case TransportProtocol.RTSP:
                    form.HTTPPort = 0;
                    form.TCP = true;
                    break;

                case TransportProtocol.HTTP:
                    form.HTTPPort = 80;
                    try
                    {
                        int index = str.IndexOf(']', 8);
                        if (index > 0)
                        {
                            index++;
                        }
                        else
                        {
                            index = str.IndexOf(':', 8);
                        }
                        if (str.Substring(index, 1) == ":")
                        {
                            index++;
                            int num2 = str.IndexOf('/', index);
                            index = int.Parse(str.Substring(index, num2 - index));
                            if (index > 0)
                            {
                                form.HTTPPort = index;
                            }
                        }
                    }
                    catch (Exception)
                    {
                    }
                    form.TCP = true;
                    break;
            }
            form.Multicast = streamType == StreamType.RTPMulticast;
            form.Address = str;
            form.RTSP = !string.IsNullOrEmpty(str);
            form.Timeout = messageTimeout;
            if ((conf != null) && (conf.Resolution != null))
            {
                form.VideoWidth = conf.Resolution.Width;
                form.VideoHeight = conf.Resolution.Height;
            }
        }

        public static void ShowMultiple(IVideoFormEvent eventConsumer, WaitHandle stopEvent, string username, string password, int timeout, GetStreamSetup getStreamSetup, int NICIndex, List<Profile> profiles, Func<StreamSetup, string, MediaUri> getStreamUri)
        {
            List<VideoStreamForm> list = new List<VideoStreamForm>();
            List<WaitHandle> list2 = new List<WaitHandle>();
            WaitHandle handle = new AutoResetEvent(false);
            foreach (Profile profile in profiles)
            {
                Profile prof = profile;
                StreamSetup setup = getStreamSetup(ref prof);
                if (prof != null)
                {
                    VideoStreamForm item = new VideoStreamForm {
                        streamSetup = setup,
                        profile = prof,
                        getStreamUri = getStreamUri,
                        messageTimeout = timeout,
                        username = username,
                        password = password,
                        signalCloseWindow = handle,
                        eventConsumer = eventConsumer,
                        NICIndex = NICIndex
                    };
                    list.Add(item);
                    list2.Add(item.eventWorkEnded);
                }
            }
            if (list.Count != 0)
            {
                try
                {
                    VideoStreamForm form2 = null;
                    foreach (VideoStreamForm form3 in list)
                    {
                        ((ManualResetEvent) form3.eventWorkEnded).Reset();
                        form3.thread.Start(form3);
                        if (WaitHandle.WaitAny(new WaitHandle[] { stopEvent, form3.eventOpened, form3.eventWorkEnded }) == 0)
                        {
                            throw new StopEventException();
                        }
                        if (form3.exception != null)
                        {
                            form2 = form3;
                            break;
                        }
                    }
                    foreach (VideoStreamForm form4 in list)
                    {
                        if ((form4.thread.ThreadState != ThreadState.Unstarted) && (form4 != form2))
                        {
                            form4.skipLog = true;
                        }
                    }
                    ((AutoResetEvent) handle).Set();
                    if (!WaitHandle.WaitAll(list2.ToArray(), timeout))
                    {
                        ((AutoResetEvent) handle).Reset();
                        throw new VideoException("Waiting timeout exceeded");
                    }
                }
                catch (Exception exception)
                {
                    foreach (VideoStreamForm form5 in list)
                    {
                        if (form5.thread.ThreadState != ThreadState.Unstarted)
                        {
                            form5.thread.Abort();
                            form5.thread.Join();
                        }
                    }
                    throw exception;
                }
                foreach (VideoStreamForm form6 in list)
                {
                    form6.thread.Join();
                    if (form6.exception != null)
                    {
                        throw form6.exception;
                    }
                }
            }
        }

        private class VideoStreamForm : IVideoFormEvent
        {
            public IVideoFormEvent eventConsumer;
            public WaitHandle eventOpened = new AutoResetEvent(false);
            public WaitHandle eventWorkEnded = new ManualResetEvent(true);
            public Exception exception;
            public Func<StreamSetup, string, MediaUri> getStreamUri;
            public int messageTimeout;
            public int NICIndex;
            public string password;
            public Profile profile;
            public WaitHandle signalCloseWindow;
            public bool skipLog;
            public List<string> skippedLog = new List<string>();
            public StreamSetup streamSetup;
            public MediaUri streamUri;
            public Thread thread = new Thread(new ParameterizedThreadStart(VideoUtils.VideoStreamForm.VW));
            public string username;

            public void FireBeginStep(string Name)
            {
                string name = "[Profile: " + this.profile.Name + "] " + Name;
                if (!this.skipLog)
                {
                    lock (this.eventConsumer)
                    {
                        this.eventConsumer.FireBeginStep(name);
                        return;
                    }
                }
                this.skippedLog.Add(name);
            }

            public void FireLogStepEvent(string Message)
            {
                if (!this.skipLog)
                {
                    lock (this.eventConsumer)
                    {
                        this.eventConsumer.FireLogStepEvent(Message);
                        return;
                    }
                }
                this.skippedLog.Add(Message);
            }

            public void FireStepPassed()
            {
                if (!this.skipLog)
                {
                    lock (this.eventConsumer)
                    {
                        this.eventConsumer.FireStepPassed();
                        return;
                    }
                }
                this.skippedLog.Add("PASSED");
            }

            public static void VW(object param)
            {
                VideoUtils.VideoStreamForm form = (VideoUtils.VideoStreamForm) param;
                try
                {
                    lock (form.eventConsumer)
                    {
                        form.streamUri = form.getStreamUri(form.streamSetup, form.profile.token);
                    }
                }
                catch (Exception exception)
                {
                    form.exception = exception;
                }
                if (form.exception == null)
                {
                    IVideoForm form2 = new VideoContainer {
                        NICIndex = form.NICIndex
                    };
                    VideoUtils.AdjustVideo(form2, form.username, form.password, form.messageTimeout, form.streamSetup.Transport.Protocol, form.streamSetup.Stream, form.streamUri, form.profile.VideoEncoderConfiguration);
                    bool flag = false;
                    try
                    {
                        flag = true;
                        form2.EventSink = form;
                        form2.OpenWindow(false);
                        ((AutoResetEvent) form.eventOpened).Set();
                        form.signalCloseWindow.WaitOne();
                        form2.CloseWindow();
                        flag = false;
                    }
                    catch (Exception exception2)
                    {
                        form.exception = exception2;
                    }
                    finally
                    {
                        if (flag)
                        {
                            form2.CloseWindow();
                        }
                        form2 = null;
                    }
                }
                ((ManualResetEvent) form.eventWorkEnded).Set();
                ((AutoResetEvent) form.signalCloseWindow).Set();
            }
        }
    }
}

